use hellorust::*;
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use serde_json::Value;
use std::sync::RwLock;

extern crate md5;

#[tokio::main]
async fn main() {
    // cache
    // cache::test();

    // httpreq
    // reqwest_client::get().await;
    // reqwest_client::test().await;

    // chrono
    // chrono_test::current_time_slice();
    // chrono_test::from_millis();

    // actix_client::test1().await;
    // actix_client::test2().await;

    // let foo = Foo {
    //     name: "jack".into(),
    //     age: 10,
    // };
    // let name = foo.name;
    // println!("name is {}", name);
    // // println!("{}", foo.name);    // foo.name has moved
    // println!("age is {}", foo.age);

    // threadlocal::test();

    // let f1 = Foo {
    //     name: "Jack".into(),
    //     age: 10,
    // };
    // let f2 = Foo {
    //     name: "Porny".into(),
    //     age: 11
    // };
    // f1.diff(&f2);

    
    // test_hash_map();

    // my_tokio::f1().await;
    // my_tokio::f2().await;

    // my_threadpool::test();
    // test_vector();

    // let imei = Some("864288031748318".into());
    // println!("{}", is_correct_imei(&imei));

    // let vs = vec!["a", "d", "e", "f", "b", "c"];
    // let mut vss = vs.clone();
    // vss.sort();
    // let s = vss.join("");

    // println!("{}: {:x}", s, md5::compute(&s));


    // my_aes::encrypt();
    my_rc4::encrypt();
}

fn is_correct_imei(imei: &Option<String>) -> bool {
    let imei = imei.as_ref().unwrap();
    if imei.len() == 15 && imei.chars().all(char::is_numeric) {
        let mut i = 0;
        let mut result: u32 = 0;
        let mut imei_chars = imei.chars();
        while i < 14 {
            let a = imei_chars.next().unwrap().to_string().parse::<u32>().unwrap();
            let b = imei_chars.next().unwrap().to_string().parse::<u32>().unwrap() * 2;
            let b = if b < 10 { b } else { b - 9 };
            result += a + b;
            i += 2;
        }
        result = result % 10;
        result = if result == 0 { 0 } else { 10 - result };

        let check = imei[imei.len() - 1 .. imei.len()].parse::<u32>().unwrap();
        return result == check;
    }

    false
}

fn test_vector() {
    let mut vec = vec![1, 5, 10, 2, 15];
    vec.sort_by(|x, y| y.cmp(&x));
    let max = vec.remove(0);
    let s_max = vec[0];
    println!("max: {:?}", max);
    println!("s_max: {:?}", s_max);
    println!("vec: {:?}", vec);
}

fn test_hash_map() {
    let foo = Foo {
        name: "Jack".into(),
        age: 10,
    };
    let mut map: HashMap<String, Foo> = HashMap::new();
    map.insert("foo1".into(), foo);
    let cache: RwLock<HashMap<String, Foo>> = RwLock::new(map);
    let r = cache.read().unwrap();
    let mut ff = r.get(&String::from("foo1")).unwrap().to_owned();
    ff.name = "james".into();
    println!("{:#?}", ff);

    let f2 = r.get(&String::from("foo1")).unwrap();
    println!("{:#?}", f2);
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Foo {
    pub name: String,
    pub age: usize
}

impl Foo {
    pub fn diff(&self, other: &Foo) -> HashMap<String, Value> {
        let mut diff: HashMap<String, Value> = HashMap::new();
        let self_map: HashMap<String, Value> = serde_json::from_str(serde_json::to_string(self).unwrap().as_str()).unwrap();
        let other_map: HashMap<String, Value> = serde_json::from_str(serde_json::to_string(other).unwrap().as_str()).unwrap();

        for key in self_map.keys() {
            if self_map.get(key) != other_map.get(key) {
                diff.insert(key.to_owned(), other_map.get(key).unwrap().to_owned());
                println!("update {}: {}", key, other_map.get(key).unwrap());
            }
        }

        diff
    }
}